# -*- coding = utf-8 -*-
# @Time：2022/3/1 11:29
# @Author：3ic
# @File：detect_num_hash.py
# @Software：PyCharm

import os
import sys
import time

import cv2
import numpy as np
import win32api
import win32con
import win32process
from PyQt5.QtWidgets import QApplication
import win32gui

DigitsDirPath = 'numbers'


def getCaptureScreen():
    hwnd = win32gui.FindWindow('LDPlayerMainFrame', '雷电模拟器')
    app = QApplication(sys.argv)
    screen = QApplication.primaryScreen()
    return hwnd, app, screen


def getOptionScreen(hwnd_, lparam):
    s = win32gui.GetWindowText(hwnd_)
    if len(s) > 3:
        global opthwnd
        opthwnd = hwnd_
        print("winfun, child_hwnd: %d   txt: %s" % (opthwnd, s))
    return 1


def setForegroundWindowByWin32GUI(hwnd):
    hForeWnd = win32gui.GetForegroundWindow()
    FormThreadID = win32api.GetCurrentThreadId()
    CWndThreadID = win32process.GetWindowThreadProcessId(hForeWnd)
    win32process.AttachThreadInput(CWndThreadID[0], FormThreadID, True)
    win32gui.ShowWindow(hwnd, win32con.SW_SHOWNORMAL)
    win32gui.SetForegroundWindow(hwnd)
    win32process.AttachThreadInput(CWndThreadID[0], FormThreadID, False)


def loadDigitsImgs(dir_path):
    digit_imgs = []
    for file_or_dir in os.listdir(dir_path):
        img = cv2.imread(os.path.join(dir_path, file_or_dir))
        img = cv2.resize(ori2Bin(img), (17, 27))  # 17, 27
        digit_imgs.append(img)
    return digit_imgs


def fastCapture(screen, hwnd, x, y, w, h):
    img = screen.grabWindow(hwnd, x, y, w, h).toImage()
    ptr = img.constBits()
    ptr.setsize(img.byteCount())
    return np.array(ptr).reshape(img.height(), img.width(), 4)


def ori2Bin(img):
    return cv2.threshold(cv2.cvtColor(img, cv2.COLOR_RGB2GRAY), 200, 255, cv2.THRESH_BINARY)[1]


def winPressKey(key, times=1, interval=0):
    key = ord(key)
    while times > 1:
        times -= 1
        win32gui.SendMessage(opthwnd, win32con.WM_KEYDOWN, key, 0)
        win32gui.SendMessage(opthwnd, win32con.WM_KEYUP, key, 0)
        time.sleep(interval)
    win32gui.SendMessage(opthwnd, win32con.WM_KEYDOWN, key, 0)
    win32gui.SendMessage(opthwnd, win32con.WM_KEYUP, key, 0)


def winClickMouse(x, y):
    client_pos = win32gui.ScreenToClient(opthwnd, (x, y))
    tmp = win32api.MAKELONG(client_pos[0], client_pos[1])
    win32gui.SendMessage(opthwnd, win32con.WM_ACTIVATE, win32con.WA_ACTIVE, 0)
    win32api.SendMessage(opthwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, tmp)
    win32api.SendMessage(opthwnd, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, tmp)


def printSec(sec):
    if sec >= 60:
        sys.stdout.write('\n1:' + str(sec - 60).zfill(2))
    else:
        sys.stdout.write('\n0:' + str(sec).zfill(2))


def _detectNumHash():
    img = fastCapture(screen, hwnd, 1595, 65, 8, 30)
    hash_val = (np.sum(img[:, :, 0] > 127) << 16) + \
               (np.sum(img[:, :, 1] > 127) << 8) + \
               (np.sum(img[:, :, 2] > 127))
    return str(hash_val)


def quitBattle():
    time.sleep(0.2)
    winClickMouse(1713, 82)
    time.sleep(0.8)
    winClickMouse(1200, 720)
    time.sleep(1.3)
    winClickMouse(1200, 720)
    time.sleep(0.2)


if __name__ == '__main__':
    hwnd, _, screen = getCaptureScreen()
    win32gui.EnumChildWindows(hwnd, getOptionScreen, None)

    setForegroundWindowByWin32GUI(hwnd)
    win32gui.SetWindowPos(hwnd, win32con.HWND_NOTOPMOST, 0, 0, 1920, 1030, win32con.SWP_SHOWWINDOW)

    digits_tile = loadDigitsImgs(DigitsDirPath)

    sec = 91
    rec_lim = 80
    rec_num = 5
    frame_cnt = 0
    last_digit = 1
    dif_cnt = 0

    time.sleep(0.1)
    winClickMouse(1600, 870)
    time.sleep(5.5)

    while sec > 0:
        frame_cnt += 1
        img = fastCapture(screen, hwnd, 1582, 65, 23, 30)
        binary = ori2Bin(img)

        best_score = -1
        best_digit = 0
        digit = -1
        for digit_tile in digits_tile:
            digit += 1
            result = cv2.matchTemplate(binary, digit_tile, cv2.TM_CCOEFF)
            score = cv2.minMaxLoc(result)[1]
            if score > best_score:
                best_score = score
                best_digit = digit

        if best_digit != last_digit:
            if dif_cnt < 5:
                dif_cnt += 1
            elif frame_cnt > 30:
                last_digit = best_digit
                dif_cnt = 0
                sec -= 1
                frame_cnt = 5
                if sec > rec_lim and best_digit != sec % 10 and best_digit == rec_num:
                    sys.stdout.write('\nrectified')
                    sec = sec // 10 * 10 + rec_num
                printSec(sec)
                for i in range(3):
                    sys.stdout.write('（' + _detectNumHash() + '）')
                    time.sleep(0.1)

        time.sleep(0.01)

    sys.stdout.write('\nFinish')
    quitBattle()